package com.yixin.hospital.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yixin.hospital.common.ApiResult;
import com.yixin.hospital.entity.domain.*;
import com.yixin.hospital.entity.dto.req.jobduty.AuthJobDutyMenuReqDTO;
import com.yixin.hospital.entity.dto.req.jobduty.JobDutyAddReqDTO;
import com.yixin.hospital.entity.dto.req.jobduty.JobDutyEditReqDTO;
import com.yixin.hospital.entity.vo.DeptAndJobDutyTreeNodeVO;
import com.yixin.hospital.entity.vo.JobDutyVO;
import com.yixin.hospital.mapper.JobDutyMapper;
import com.yixin.hospital.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.yixin.hospital.enums.ResponseCodeEnum.*;

/**
* @author Administrator
* @description 针对表【job_duty(职务表)】的数据库操作Service实现
* @createDate 2024-05-23 15:55:57
*/
@Service
public class JobDutyServiceImpl extends ServiceImpl<JobDutyMapper, JobDuty>
    implements JobDutyService{

    @Resource
    private JobDutyMenuService jobDutyMenuService;
    @Resource
    private DeptService deptService;
    @Resource
    private UserService userService;
    @Resource
    private UserMenuService userMenuService;


    @Override
    public ApiResult<List<JobDutyVO>> allList(Long deptId) {
        List<JobDuty> list;
        if (Objects.isNull(deptId)) list = this.list();
        else list = this.list(new LambdaQueryWrapper<JobDuty>().eq(JobDuty::getDeptId, deptId));
        List<JobDutyVO> jobDutyVOS = BeanUtil.copyToList(list, JobDutyVO.class);
        for (JobDutyVO jobDutyVO : jobDutyVOS) {
            Dept dept = deptService.getById(jobDutyVO.getDeptId());
            jobDutyVO.setDeptName(dept.getName());
        }
        return ApiResult.success(jobDutyVOS);
    }

    @Override
    public ApiResult<List<DeptAndJobDutyTreeNodeVO>> deptJobDutyTree(Long deptId) {
        LambdaQueryWrapper<Dept> deptQueryWrapper = new LambdaQueryWrapper<>();
        deptQueryWrapper.eq(Dept::getId, deptId);
        Dept curDept = deptService.getOne(deptQueryWrapper);
        List<Dept> allDeptList = deptService.list();
        DeptAndJobDutyTreeNodeVO deptTreeVO = buildDeptTree(allDeptList, curDept);
        return ApiResult.success(Arrays.asList(deptTreeVO));
    }

    @Override
    public ApiResult<?> listByDeptId(Long deptId) {
        LambdaQueryWrapper<JobDuty> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(JobDuty::getDeptId, deptId);
        List<JobDuty> list = this.list(queryWrapper);
        return ApiResult.success(list);
    }

    @Override
    public ApiResult add(JobDutyAddReqDTO jobAddReqDTO, String userName) {
        if (Objects.equals(jobAddReqDTO.getIsManager(), 1)) {
            LambdaQueryWrapper<Dept> deptQueryWrapper = new LambdaQueryWrapper<>();
            deptQueryWrapper.eq(Dept::getId, jobAddReqDTO.getDeptId()).eq(Dept::getManager, 1);
            long count = deptService.count(deptQueryWrapper);
            if (count != 0) ApiResult.error(DEPT_MANAGER_EXIT);
        }
        JobDuty jobDuty = new JobDuty();
        jobDuty.setName(jobAddReqDTO.getName());
        jobDuty.setDeptId(jobAddReqDTO.getDeptId());
        jobDuty.setIsManager(jobAddReqDTO.getIsManager());
        jobDuty.setIsDesensitization(jobAddReqDTO.getIsDesensitization());
        jobDuty.setCreatedBy(userName);
        jobDuty.setUpdatedBy(userName);
        this.save(jobDuty);
        if (!CollectionUtils.isEmpty(jobAddReqDTO.getMenuList())) {
            for (Long menuId : jobAddReqDTO.getMenuList()) {
                JobDutyMenu jobDutyMenu = new JobDutyMenu();
                jobDutyMenu.setJobDutyId(jobDuty.getId());
                jobDutyMenu.setMenuId(menuId);
                jobDutyMenu.setCreatedBy(userName);
                jobDutyMenu.setUpdatedBy(userName);
                jobDutyMenuService.save(jobDutyMenu);
            }
        }
        return ApiResult.success();
    }

    @Override
    public ApiResult edit(JobDutyEditReqDTO jobEditReqDTO, String userName) {
        JobDuty jobDuty = new JobDuty();
        jobDuty.setId(jobEditReqDTO.getId());
        jobDuty.setName(jobEditReqDTO.getName());
        jobDuty.setDeptId(jobEditReqDTO.getDeptId());
        jobDuty.setIsManager(jobEditReqDTO.getIsManager());
        jobDuty.setIsDesensitization(jobEditReqDTO.getIsDesensitization());
        jobDuty.setUpdatedBy(userName);
        this.updateById(jobDuty);
        LambdaQueryWrapper<JobDutyMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(JobDutyMenu::getJobDutyId, jobEditReqDTO.getId());
        jobDutyMenuService.remove(queryWrapper);
        if (!CollectionUtils.isEmpty(jobEditReqDTO.getMenuList())) {
            for (Long menuId : jobEditReqDTO.getMenuList()) {
                JobDutyMenu jobDutyMenu = new JobDutyMenu();
                jobDutyMenu.setJobDutyId(jobEditReqDTO.getId());
                jobDutyMenu.setMenuId(menuId);
                jobDutyMenu.setCreatedBy(userName);
                jobDutyMenu.setUpdatedBy(userName);
                jobDutyMenuService.save(jobDutyMenu);
            }
        }
        List<User> list = userService.list();
        for (User user : list) {
            if (Objects.isNull(user.getJobDuty()) || StringUtils.isBlank(user.getJobDuty())) continue;
            List<String> jobDutyIds = Arrays.asList(user.getJobDuty().split(","));
            if (jobDutyIds.contains(String.valueOf(jobEditReqDTO.getId()))) {
                updateUserMenu(user, jobDutyIds, userName);
            }
        }
        return ApiResult.success();
    }

    @Override
    public ApiResult authJobMenu(AuthJobDutyMenuReqDTO authJobMenuReqDTO, String userName) {
        JobDutyMenu jobMenu = new JobDutyMenu();
        jobMenu.setJobDutyId(authJobMenuReqDTO.getJobDutyId());
        jobMenu.setMenuId(authJobMenuReqDTO.getMenuId());
        jobMenu.setCreatedBy(userName);
        jobMenu.setUpdatedBy(userName);
        jobDutyMenuService.save(jobMenu);
        return ApiResult.success();
    }

    @Override
    public ApiResult<?> parentJobDuty(String jobDutyId) {
        JobDuty curJobDuty = this.getById(jobDutyId);
        LambdaQueryWrapper<JobDuty> queryWrapper = new LambdaQueryWrapper<>();
        Dept curDept = deptService.getById(curJobDuty.getDeptId());
        // 管理岗，返回父部门管理岗职务
        if (Objects.equals(curJobDuty.getIsManager(), 1)) {
            Dept pDept = deptService.getById(curDept.getPid());
            if (Objects.isNull(pDept)) return ApiResult.error(PARENT_DEPT_NOT_EXIT.getCode(), PARENT_DEPT_NOT_EXIT.getMsg());
            queryWrapper.eq(JobDuty::getDeptId, pDept.getId());
            queryWrapper.eq(JobDuty::getIsManager, 1);
            JobDuty jobDuty = this.getOne(queryWrapper);
            if (Objects.isNull(jobDuty)) return ApiResult.error(DEPT_MANAGER_NOT_EXIT.getCode(), pDept.getName() + DEPT_MANAGER_NOT_EXIT.getMsg());
            JobDutyVO jobDutyVO = new JobDutyVO();
            BeanUtils.copyProperties(jobDuty, jobDutyVO);
            jobDutyVO.setDeptId(pDept.getId());
            jobDutyVO.setDeptName(pDept.getName());
            return ApiResult.success(jobDutyVO);
        }
        // 非管理岗，返回管理岗职务
        queryWrapper.eq(JobDuty::getDeptId, curJobDuty.getDeptId());
        queryWrapper.eq(JobDuty::getIsManager, 1);
        JobDuty jobDuty = this.getOne(queryWrapper);
        if (Objects.isNull(jobDuty)) return ApiResult.error(DEPT_MANAGER_NOT_EXIT.getCode(), curDept.getName() + DEPT_MANAGER_NOT_EXIT.getMsg());
        JobDutyVO jobDutyVO = new JobDutyVO();
        BeanUtils.copyProperties(jobDuty, jobDutyVO);
        jobDutyVO.setDeptId(curDept.getId());
        jobDutyVO.setDeptName(curDept.getName());
        return ApiResult.success(jobDutyVO);
    }

    private void updateUserMenu(User user, List<String> jobDutyIds, String userName) {
        Set<Long> menuIds = new HashSet<>();
        for (String jobDutyId : jobDutyIds) {
            List<JobDutyMenu> list = jobDutyMenuService.list(new LambdaQueryWrapper<JobDutyMenu>().eq(JobDutyMenu::getJobDutyId, jobDutyId));
            if (!CollectionUtils.isEmpty(list)) {
                menuIds.addAll(list.stream().map(JobDutyMenu::getMenuId).collect(Collectors.toList()));
            }
        }
        userMenuService.remove(new LambdaQueryWrapper<UserMenu>().eq(UserMenu::getUserId, user.getId()));
        List<UserMenu> dbUserMenu = new ArrayList<>();
        for (Long menuId : menuIds) {
            UserMenu userMenu = new UserMenu();
            userMenu.setUserId(user.getId());
            userMenu.setMenuId(menuId);
            userMenu.setUpdatedBy(userName);
            userMenu.setCreatedBy(userName);
            dbUserMenu.add(userMenu);
        }
        userMenuService.saveBatch(dbUserMenu);
    }


    private DeptAndJobDutyTreeNodeVO buildDeptTree(List<Dept> allDeptList, Dept curDept) {
        DeptAndJobDutyTreeNodeVO deptTreeVO = new DeptAndJobDutyTreeNodeVO();
        deptTreeVO.setId(curDept.getId());
        deptTreeVO.setValue(new DeptAndJobDutyTreeNodeVO.valueVo(curDept.getId(), curDept.getName(), 0));
        deptTreeVO.setLabel(curDept.getName());
        deptTreeVO.setType(0);
        buildDeptChild(deptTreeVO, allDeptList);
        List<JobDuty> jobDutyList = this.list();
        buildJobDutyChild(deptTreeVO, jobDutyList);
        return deptTreeVO;
    }

    private void buildJobDutyChild(DeptAndJobDutyTreeNodeVO deptTreeVO, List<JobDuty> jobDutyList) {
        List<DeptAndJobDutyTreeNodeVO> children = deptTreeVO.getChildren();
        // dept add job
        for (JobDuty jobDuty : jobDutyList) {
            if (deptTreeVO.getType() == 0 && jobDuty.getDeptId() == deptTreeVO.getId()) {
                deptTreeVO.getChildren().add(new DeptAndJobDutyTreeNodeVO(jobDuty.getId(), new DeptAndJobDutyTreeNodeVO.valueVo(jobDuty.getId(), jobDuty.getName(), 1), jobDuty.getName(), 1, null));
            }
        }
        // children add job
        if (!CollectionUtils.isEmpty(children)) {
            for (DeptAndJobDutyTreeNodeVO child : children) {
                buildJobDutyChild(child, jobDutyList);
            }
        }
    }

    private void buildDeptChild(DeptAndJobDutyTreeNodeVO deptTreeVO, List<Dept> deptList) {
        for (Dept dept : deptList) {
            if (dept.getPid().compareTo(deptTreeVO.getId()) == 0) {
                DeptAndJobDutyTreeNodeVO childVo = new DeptAndJobDutyTreeNodeVO();
                childVo.setValue(new DeptAndJobDutyTreeNodeVO.valueVo(dept.getId(), dept.getName(), 0));
                childVo.setId(dept.getId());
                childVo.setLabel(dept.getName());
                childVo.setType(0);
                buildDeptChild(childVo, deptList);
                deptTreeVO.getChildren().add(childVo);
            }
        }
    }


}




